﻿using KPIS.GERP.Models;
using KPIS.GERP.Models.Class;
using KPIS.GERP.Models.ICM;
using KPIS.GERP.Models.SYS;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.ServiceModel;
using System.Web.Mvc;

namespace KPIS.GERP.WCF.GIMS
{
    [ServiceContract]
    public interface IPurchaseRequestService
    {
        [OperationContract]
        string GenNewPr(int year, int month);

        [OperationContract]
        IEnumerable<PurchaseRequest> GenNewPrAndInsertAndSelect(int year, int month, int createByUserId, int committeeGroupId);

        [OperationContract]
        IEnumerable<PurchaseRequest> Select(PurchaseRequest criteriaModel = null, List<string> includeSubObjectString = null);

        [OperationContract]
        IEnumerable<Bidder> SelectNotPo();

        [OperationContract]
        int Insert(PurchaseRequest model, int createByUserId);

        [OperationContract]
        void Update(PurchaseRequest model, int updateByUserId);

        [OperationContract]
        int UpdateRet(PurchaseRequest model, int updateByUserId);

        [OperationContract]
        void Delete(int id, int deleteByUserId);

        [OperationContract]
        int GetPprIdOfComitteeByPrId(int prId);
    }
    
    [System.ServiceModel.Activation.AspNetCompatibilityRequirements(RequirementsMode = System.ServiceModel.Activation.AspNetCompatibilityRequirementsMode.Allowed)]
    public class PurchaseRequestService : IPurchaseRequestService
    {
        public string GenNewPr(int year, int month)
        {
            try
            {
                year = DateTime.Now.Year;
                month = DateTime.Now.Month;

                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseRequest> query = context.PurchaseRequests;

                    int cnt = query.Where(a => a.CreatedWhen.Value.Year == year && a.CreatedWhen.Value.Month == month).OrderByDescending(a => a.PrId).Count();

                    string data = "PR-" + year.ToString("0000") + month.ToString("00") + "-" + (cnt + 1).ToString("000");

                    return data;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IEnumerable<PurchaseRequest> GenNewPrAndInsertAndSelect(int year, int month, int createByUserId, int committeeGroupId)
        {
            try
            {
                year = DateTime.Now.Year;
                month = DateTime.Now.Month;

                //string newPr = GenNewPr(year,month);
                //pr.Code = newPr;
                PurchaseRequest pr = new PurchaseRequest();
                pr.BgYear = year;
                pr.CreatedBy = createByUserId;
                pr.CreatedWhen = DateTime.Now;
                pr.CommitteeGroupId = committeeGroupId;
                int id = Insert(pr, createByUserId);

                return Select(new PurchaseRequest{PrId = id}, null);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IEnumerable<PurchaseRequest> Select(PurchaseRequest criteriaModel = null, List<string> includeSubObjectString = null)
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    IQueryable<PurchaseRequest> query = context.PurchaseRequests;

                    if (includeSubObjectString != null)
                    {
                        query = includeSubObjectString.Aggregate(query, (current, includePath) => current.Include(includePath));
                    }

                    if (criteriaModel != null)
                    {
                        object[] param;
                        query = query.Where(KPIS.GERP.Models.Class.Utility.GenerateWhereString(criteriaModel, out param), param);
                    }

                    var x = query.ToList();
                    return x;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public IEnumerable<Bidder> SelectNotPo()
        {
            try
            {
                using (var context = new GERPContext(false))
                {
                    //IQueryable<PurchaseRequest> query = (from pr in context.PurchaseRequests
                    //                                     join pri in context.PurchaseRequestItems.DefaultIfEmpty() on pr.PrId equals pri.PrId into pris
                    //                                     from pri in pris.DefaultIfEmpty()
                    //                                     join bq in context.BidderQuotations.DefaultIfEmpty() on pri.PrItemId equals bq.PrItemId into bqs
                    //                                     from bq in bqs.DefaultIfEmpty()
                    //                                     join bd in context.Bidders.DefaultIfEmpty() on bq.BidderId equals bd.BidderId into bds
                    //                                     from bd in bds.DefaultIfEmpty()
                    //                                     join poi in context.PurchaseOrderItems.DefaultIfEmpty() on bq.BidderQuoId equals poi.BidderQuoId into pois
                    //                                     from poi in pois.DefaultIfEmpty()
                    //                                     where poi.PoItemId == null
                    //                                     && pr.RecordStatus == RecordStatus.ApprovedStatus
                    //                                     && (pr.MasPurchaseMethod.IsBid ?? false ? bd.WinnerStatus == "1" : true )
                    //                                     select pr
                    //                                    ).Distinct();
                    IQueryable<Bidder> query = (from bd in context.Bidders
                                                join bdq in context.BidderQuotations.DefaultIfEmpty() on bd.BidderId equals bdq.BidderId into bdqs
                                                from bdq in bdqs.DefaultIfEmpty()
                                                join pri in context.PurchaseRequestItems.DefaultIfEmpty() on bdq.PrItemId equals pri.PrItemId into pris
                                                from pri in pris.DefaultIfEmpty()
                                                join pr in context.PurchaseRequests.DefaultIfEmpty() on pri.PrId equals pr.PrId into prs
                                                from pr in prs.DefaultIfEmpty()
                                                join po in context.PurchaseOrders.Where(m => m.RecordStatus != RecordStatus.DeletedStatus).DefaultIfEmpty() on bd.BidderId equals po.BidderId into pos
                                                from po in pos.DefaultIfEmpty()
                                                where po.BidderId == null
                                                      && pr.RecordStatus == RecordStatus.ApprovedStatus
                                                      && (pr.MasPurchaseMethod.IsBid ?? false ? bd.WinnerStatus == "1" : true)
                                                select bd
                                               ).Distinct();
                    query = query
                        .Include("PurchaseRequest.MasPurchaseMethod")
                        .Include("MasContact")
                        .Include("PurchaseRequest.Priority");

                    var x = query.ToList();
                    return x;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int Insert(PurchaseRequest model, int createByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    model.RecordStatus = RecordStatus.WaitStatus;
                    model.CreatedBy = createByUserId;
                    model.CreatedWhen = DateTime.Now;
                    model.Code = CodeGenerate.GetNextCode(CodeGenerate.TransectionType.PurchaseRequest, "");
                    context.PurchaseRequests.Add(model);
                    context.SaveChanges();

                    return model.PrId;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Update(PurchaseRequest model, int updateByUserId)
        {
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    context.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public int UpdateRet(PurchaseRequest model, int updateByUserId)
        {
            int ret = 0;
            try
            {
                using (var context = new GERPContext())
                {
                    context.Entry(model).State = EntityState.Modified;
                    model.UpdatedBy = updateByUserId;
                    model.UpdatedWhen = DateTime.Now;
                    ret = context.SaveChanges();
                }
                return ret;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public void Delete(int id, int deleteByUserId)
        { 
            using (var context = new GERPContext(true))
            {
                var pr2Del = context.PurchaseRequests.Find(id);
                if (pr2Del == null) return;

                pr2Del.RecordStatus = RecordStatus.DeletedStatus;
                pr2Del.UpdatedBy = deleteByUserId;
                pr2Del.UpdatedWhen = DateTime.Now;
                context.SaveChanges();

                var prItems = context.PurchaseRequestItems.Where(m => m.PrId == id).ToList();
                foreach (var prItem in prItems)
                {
                    prItem.RecordStatus = "D";
                    var pprItems = context.PrePurchaseRequestItems.Where(m => m.PrItemId == prItem.PrItemId).ToList();
                    context.SaveChanges();

                    foreach (var pprItem in pprItems)
                    {
                        pprItem.PrItemId = null;
                        context.SaveChanges();
                    }
                }

            } 
        }

        public int GetPprIdOfComitteeByPrId(int prId)
        {
            using (var context = new GERPContext(true))
            {
                var prItemId = context.PurchaseRequestItems.First(o => o.PrId == prId).PrItemId;
                var pprId = context.PrePurchaseRequestItems.First(o => o.PrItemId == prItemId).PprId;
                return pprId;
            }
        }
    }
}